/*
 * StructureDTD.cpp
 *
 *  Created on: 22 mars 2011
 *      Author: lgu
 */

using namespace std;
#include <iostream>
#include "StructureDTD.h"




DTDEntite::DTDEntite()
{

}

DTDEntite::~DTDEntite()
{

}


bool DTDEntite::isElement()
{
	DTDElement* pEl;
	pEl = dynamic_cast<DTDElement*>(this);
	if (pEl == 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

bool DTDEntite::isEnsemble()
{
	DTDEnsemble* pEn;
	pEn = dynamic_cast<DTDEnsemble*>(this);
	if (pEn == 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

string DTDEntite::getAffichage()
{
	return "<vide>";
}

//-----------------------------------------------------
DTDElement::DTDElement() : DTDEntite()
{

}

DTDElement::DTDElement(string unNom) : DTDEntite()
{
	name = unNom;
}

DTDElement::~DTDElement()
{

}

string DTDElement::getName()
{
	return name;
}


string DTDElement::getAffichage()
{
	return name;
}

//-----------------------------------------------------
DTDEnsemble::DTDEnsemble() : DTDEntite()
{
	sousEntites.reserve(100);
	relations.reserve(100);
}

DTDEnsemble::DTDEnsemble(vector<AppEntite> listeSE, vector<int> relationSE) : DTDEntite()
{
	sousEntites.reserve(100);
	relations.reserve(100);

	sousEntites = listeSE;
	relations = relationSE;
}

DTDEnsemble::~DTDEnsemble()
{

}

void DTDEnsemble::ajouterEntite(AppEntite unSE, int relation)
{
	sousEntites.push_back(unSE);
	relations.push_back(relation);
}

vector<AppEntite> DTDEnsemble::getEntites()
{
	return sousEntites;
}

vector<int> DTDEnsemble::getRelations()
{
	return relations;
}

string DTDEnsemble::getAffichage()
{

	string strAffiche = "(";
	unsigned int i;
	for (i=0; i<=relations.size()-1;i++)
	{
		strAffiche = strAffiche + sousEntites.at(i).getAffichage();
		if (relations.at(i)==0)
		{
			strAffiche = strAffiche + " ";
		}
		else
		if (relations.at(i)==1)
		{
			strAffiche = strAffiche + ",";
		}
		else
		if (relations.at(i)==2)
		{
			strAffiche = strAffiche + "|";
		}

	}
	strAffiche = strAffiche + sousEntites.at(relations.size()).getAffichage();
	strAffiche = strAffiche + ")";
	return strAffiche;
}

//------------------------------------------------------------
AppEntite::AppEntite()
{

}

AppEntite::AppEntite(DTDEntite* unEntite, int unCard)
{
	if (unEntite->isElement())
	{
		DTDElement* pEl = dynamic_cast<DTDElement*>(unEntite);
		string nom =pEl->getName();
		contenuAppEntite = new DTDElement(nom);
	}
	else
	if (unEntite->isEnsemble())
	{
		DTDEnsemble* pEn = dynamic_cast<DTDEnsemble*>(unEntite);
		vector<AppEntite> listeSE = pEn->getEntites();
		vector<int> listeRE = pEn->getRelations();
		contenuAppEntite = new DTDEnsemble(listeSE, listeRE);
	}
	typeCardinalite = unCard;
}

DTDEntite* AppEntite::getContenu()
{
	return this->contenuAppEntite;
}

int AppEntite::getTypeCard()
{
	return this->typeCardinalite;
}

string AppEntite::getAffichage()
{
	string str;
	if (contenuAppEntite->isElement())
	{
		DTDElement* pEl = dynamic_cast<DTDElement*>(contenuAppEntite);
		str = pEl->getAffichage();
	}
	else
	if (contenuAppEntite->isEnsemble())
	{
		DTDEnsemble* pEn = dynamic_cast<DTDEnsemble*>(contenuAppEntite);
		str = pEn->getAffichage();
	}

	if (typeCardinalite == 0)
	{
		str = str;
	}
	else
	if (typeCardinalite == 1)
	{
		str = str + "+";
	}
	else
	if (typeCardinalite == 2)
	{
		str = str + "*";
	}
	else
	if (typeCardinalite == 3)
	{
		str = str + "?";
	}

	return str;
}


int AppEntite::verifierStructure(const vector<string> &uneListeXML, unsigned int &pos)
{
	//int etat = 0;
		//	typeEtat:
		//		0 : Pas d'erreur
		//		1 : Erreur
	unsigned int tempPos = pos;
	if (contenuAppEntite->isElement())
	{
		DTDElement* pEl = dynamic_cast<DTDElement*>(contenuAppEntite);
		if (typeCardinalite==0)	//1..1
		{
			if ((pEl->getName()==uneListeXML.at(tempPos))&&(tempPos<uneListeXML.size()))
			{
				tempPos++;
				return 0;
			}
			else
			{
				return 1;
			}
		}
		else
		if (typeCardinalite==1)	//1..n
		{
			if ((pEl->getName()==uneListeXML.at(tempPos))&&(tempPos<uneListeXML.size()))
			{
				tempPos++;
				while ((pEl->getName()==uneListeXML.at(tempPos))&&(tempPos<uneListeXML.size()))
				{
					tempPos++;

				}
				return 0;
			}
			else
			{
				return 1;
			}
		}
		else
		if (typeCardinalite==2)	//0..n
		{
			while ((pEl->getName()==uneListeXML.at(tempPos))&&(tempPos<uneListeXML.size()))
			{
				tempPos++;
			}
			return 0;

		}
		else
		if (typeCardinalite==3)	//0..1
		{
			if ((pEl->getName()==uneListeXML.at(tempPos))&&(tempPos<uneListeXML.size()))
			{
				tempPos++;
			}
			return 0;

		}

		pos = tempPos;
		//=======Le judgement de cardinalite pour un element est fini.
	}
	else
	if (contenuAppEntite->isEnsemble())
	{
		if ((pos==uneListeXML.size()))
		{
			return 0;

		}
		else
		{
			return 1;
		}


		DTDEnsemble* pEn = dynamic_cast<DTDEnsemble*>(contenuAppEntite);
		if (typeCardinalite==0)	//1..1
		{
			if (pEn->getRelations().at(0)==1)	//COMMA
			{
				for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
				{
					if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 1)
					{
						return 1;
					}
				}
			}
			else
			if (pEn->getRelations().at(0)==2)	//PIPE
			{
				for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
				{
					bool flag = false;
					if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 0)
					{
						flag = true;
					}
					if (flag == false)
					{
						return 1;
					}
				}
			}
		}
		else
		if (typeCardinalite==1)	//1..n
		{
			bool flag1n = false;
			if (pEn->getRelations().at(0)==1)	//COMMA
			{
				for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
				{
					if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 1)
					{
						return 1;
					}
				}
				flag1n = true;
			}
			else
			if (pEn->getRelations().at(0)==2)	//PIPE
			{
				for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
				{
					bool flag = false;
					if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 0)
					{
						flag = true;
					}
					if (flag == false)
					{
						return 1;
					}
				}
				flag1n = true;
			}

			if (flag1n == false)
			{
				return 1;
			}

			bool flagFin = true;
			while (flagFin == true)
			{
				tempPos = pos;
				if (pEn->getRelations().at(0)==1)	//COMMA
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 1)
						{
							flagFin = false;
						}
					}

				}
				else
				if (pEn->getRelations().at(0)==2)	//PIPE
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						bool flag = false;
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 0)
						{
							flag = true;
						}
						if (flag == false)
						{
							flagFin = false;
						}
					}

				}

			}
			pos = tempPos;


		}
		else
		if (typeCardinalite==2)	//0..n
		{
			bool flagFin = true;
			while (flagFin == true)
			{
				tempPos = pos;
				if (pEn->getRelations().at(0)==1)	//COMMA
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 1)
						{
							flagFin = false;
						}
					}

				}
				else
				if (pEn->getRelations().at(0)==2)	//PIPE
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						bool flag = false;
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 0)
						{
							flag = true;
						}
						if (flag == false)
						{
							flagFin = false;
						}
					}

				}

			}
			pos = tempPos;


		}
		else
		if (typeCardinalite==3)	//0..1
		{
			bool flagFin = true;
			if (flagFin == true)
			{
				tempPos = pos;
				if (pEn->getRelations().at(0)==1)	//COMMA
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 1)
						{
							flagFin = false;
						}
					}

				}
				else
				if (pEn->getRelations().at(0)==2)	//PIPE
				{
					for (unsigned int i=0; i<=pEn->getEntites().size()-1;i++)
					{
						bool flag = false;
						if (pEn->getEntites().at(i).verifierStructure(uneListeXML, pos) == 0)
						{
							flag = true;
						}
						if (flag == false)
						{
							flagFin = false;
						}
					}

				}

			}
			if (flagFin == false)
			{
				pos = tempPos;
			}

		}
		//=======Le judgement de cardinalite pour un ensemble est fini.
	}



}

//============================================
DTDPhrase::DTDPhrase()
{

}

DTDPhrase::~DTDPhrase()
{

}

bool DTDPhrase::isElement()
{
	DTDPhraseElement* pPE;
	pPE = dynamic_cast<DTDPhraseElement*>(this);
	if (pPE == 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

bool DTDPhrase::isAttlist()
{
	DTDPhraseAttlist* pPA;
	pPA = dynamic_cast<DTDPhraseAttlist*>(this);
	if (pPA == 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}


//=========================================
DTDPhraseElement::DTDPhraseElement() : DTDPhrase()
{

}

DTDPhraseElement::DTDPhraseElement(DTDElement unEle, int type) : DTDPhrase()
{
	elementCorr = unEle;
	typeRelationCorr = type;
}


DTDPhraseElement::~DTDPhraseElement()
{

}


bool DTDPhraseElement::ajouterEnsemble(DTDEnsemble unEnsem, int unCard = 0)
{
	if (typeRelationCorr!=0)
	{
		return false;
	}
	else
	{
		ensembleCorr= AppEntite(&unEnsem, unCard);
	}
	return true;
}

DTDElement DTDPhraseElement::getElementCorr()
{
	return this->elementCorr;
}

int DTDPhraseElement::getTypeRelationCorr()
{
	return this->typeRelationCorr;
}

AppEntite DTDPhraseElement::getEnsembleCorr()
{
	return this->ensembleCorr;
}


string DTDPhraseElement::getAffichage()
{
	string str ="<!ELEMENT "+elementCorr.getAffichage()+" ";
	if (typeRelationCorr == 0)
	{
		str = str + ensembleCorr.getAffichage()+">";
	}
	else
	if (typeRelationCorr == 1)
	{
		str = str + "EMPTY>";
	}
	else
	if (typeRelationCorr == 2)
	{
		str = str + "ANY>";
	}
	else
	if (typeRelationCorr == 3)
	{
		str = str + "(#PCDATA)>";
	}
	else
	if (typeRelationCorr == 4)
	{
		str = str + "(#CDATA)>";
	}

	return str;
}




int DTDPhraseElement::verifierStructure(const vector<string> &uneListeXML)
{
	unsigned int position = 0;
	return this->ensembleCorr.verifierStructure(uneListeXML, position);
}

//======================================================

DTDPhraseAttlist::DTDPhraseAttlist() : DTDPhrase()
{

}

DTDPhraseAttlist::DTDPhraseAttlist(vector<string> listeNom, int unTypeCorr, int unTypeImplied) : DTDPhrase()
{
	nomAttlist = listeNom;
	typeCorr = unTypeCorr;
	typeImplied = unTypeImplied;
}

DTDPhraseAttlist::~DTDPhraseAttlist()
{

}

string DTDPhraseAttlist::getAffichage()
{
	string str = "<!ATTLIST ";
	for (unsigned int i=0; i<=nomAttlist.size()-1;i++)
	{
		str = str + nomAttlist.at(i) + " ";
	}
	if (typeCorr == 0)
	{
		str=str;
	}
	else
	if (typeCorr == 1)
	{
		str=str + "PCDATA ";
	}
	else
	if (typeCorr == 2)
	{
		str=str + "CDATA ";
	}

	if (typeImplied == 0)
	{
		str = str;
	}
	else
	if (typeImplied == 1)
	{
		str = str + "#IMPLIED";
	}
	else
	if (typeImplied == 2)
	{
		str = str;
	}

	str = str + ">";

	return str;
}


StructureEntiteDTD::StructureEntiteDTD()
{
	contenu.reserve(100);
}


void StructureEntiteDTD::ajouterPhrase(DTDPhrase* unContenu)
{
	if (unContenu->isElement())
	{
		DTDPhraseElement* pPE = dynamic_cast<DTDPhraseElement*>(unContenu);
		contenu.push_back(pPE);
	}
	else
	if (unContenu->isAttlist())
	{
		DTDPhraseAttlist* pPA = dynamic_cast<DTDPhraseAttlist*>(unContenu);
		contenu.push_back(pPA);
	}

}

vector<string> StructureEntiteDTD::getAffichage()
{
	vector<string> vecStr;
	for (unsigned int i=0; i<=contenu.size()-1; i++)
	{
		if (contenu.at(i)->isElement())
		{
			DTDPhraseElement* pPE = dynamic_cast<DTDPhraseElement*>(contenu.at(i));
			vecStr.push_back(pPE->getAffichage());
		}
		else
		if (contenu.at(i)->isAttlist())
		{
			DTDPhraseAttlist* pPA = dynamic_cast<DTDPhraseAttlist*>(contenu.at(i));
			vecStr.push_back(pPA->getAffichage());
		}

	}

	return vecStr;
}

DTDPhraseElement* StructureEntiteDTD::getElement(string unNom)
{
	for (unsigned int i=0; i<=contenu.size()-1; i++)
	{
		if (contenu.at(i)->isElement())
		{
			DTDPhraseElement* pPE = dynamic_cast<DTDPhraseElement*>(contenu.at(i));
			if (pPE->getElementCorr().getName()==unNom)
			{
				return pPE;
			}
		}

	}
	return 0;
}





//============================================

/*int main()
{
	DTDElement doc("doc");
	DTDElement auteur("auteur");
	DTDElement chapitre("chapitre");
	DTDElement paragraphe("paragraphe");

	cout << "1" << endl;
	cout << chapitre.getAffichage() << endl;

	AppEntite appAuteur(&auteur, 0);
	AppEntite appChapitre(&chapitre, 2);
	AppEntite appParagraphe(&paragraphe, 1);

	cout << "2" << endl;
	cout << appChapitre.getAffichage() << endl;


	vector<AppEntite> vectEntite;
	vectEntite.push_back(appAuteur);
	vectEntite.push_back(appChapitre);
	vectEntite.push_back(appParagraphe);

	cout << "3" << endl;

	vector<int> vectRelation;
	vectRelation.push_back(1);
	vectRelation.push_back(1);

	cout << "4" << endl;


	DTDEnsemble ensemble1(vectEntite, vectRelation);

	cout << "5" << endl;
	cout << ensemble1.getAffichage() << endl;

	DTDPhraseElement DTDPhEle(doc, 0);
	DTDPhEle.ajouterEnsemble(ensemble1,1);

	cout << "6" << endl;

	for (unsigned int i=0; i<=vectEntite.size()-1;i++)
	{
		cout << vectEntite.at(i).getAffichage() << " ";
	}
	cout << endl;

	cout << "7" << endl;

	cout << DTDPhEle.getAffichage() << endl;

	vector<string> vStr;
	vStr.push_back("eee");
	vStr.push_back("rrr");

	DTDPhraseAttlist DTDPhAtt(vStr, 2, 1);

	cout << "8" << endl;
	cout << DTDPhAtt.getAffichage() << endl;

	StructureEntiteDTD sDTD;
	sDTD.ajouterPhrase(&DTDPhAtt);
	sDTD.ajouterPhrase(&DTDPhEle);
	vector<string> vect = sDTD.getAffichage();

	cout << "9" << endl;
	for (unsigned int i=0; i<=vect.size()-1; i++)
	{
		cout << vect.at(i) << endl;

	}
	cout << endl;

	return 0;
}*/
